use crossterm::event::{Event, KeyCode};
use rand::prelude::*;
use std::any::Any;
use log::debug;
use tge::{
    context::Context,
    event::event_emit,
    game::Model,
    //timer_cancel, timer_fire, timer_register,
    util::{Dir, Point},
};

pub const MOONW: usize = 80;
pub const MOONH: usize = 40;

enum MoonState {
    Normal,
    OverSelf,
    OverBorder,
}

pub struct MoonBullet {
    pub pos: Point, 
}

impl MoonBullet {
    pub fn new(x: u16, y: u16) -> Self {
        Self {
            pos: Point {x, y},
        }
    }
}

pub struct MoonModel {
    pub mainship_pos: Point,
    pub bullets: Vec<MoonBullet>,
}


impl MoonModel {
    pub fn new() -> Self {
        Self {
            mainship_pos: Point { x: 0, y: 0 },
            bullets: vec![],
        }
    }

    pub fn act(&mut self, d: Dir, context: &mut Context) {
        let dx: i16;
        let dy: i16;
        let cx: i16;
        let cy: i16;
        match d {
            Dir::Up => {
                dx = 0;
                dy = -1
            }
            Dir::Down => {
                dx = 0;
                dy = 1
            }
            Dir::Left => {
                dx = -1;
                dy = 0
            }
            Dir::Right => {
                dx = 1;
                dy = 0
            }
            _ => {
                dx = 0;
                dy = 0
            }
        }
        cx = self.mainship_pos.x as i16 + dx;
        cy = self.mainship_pos.y as i16 + dy;
        if cx >= MOONW as i16 || cy >= MOONH as i16|| cx < 0 || cy < 0 {
            return;
        }
        self.mainship_pos.x = cx as u16;
        self.mainship_pos.y = cy as u16;

        event_emit("Moon.RedrawGrid");
    }
}

impl Model for MoonModel {
    fn init(&mut self, context: &mut Context) {
        let mut rng = thread_rng();
        self.mainship_pos.x = rng.gen_range(0..MOONW) as u16;
        self.mainship_pos.y = rng.gen_range(0..MOONH) as u16;
        context.input_events.clear();
        context.state = MoonState::Normal as u8;
        event_emit("Moon.RedrawGrid");
    }

    fn handle_input(&mut self, context: &mut Context,  _dt: f32) {
        let es = context.input_events.clone();
        for e in &es {
            match e {
                Event::Key(key) => {
                    let mut d: Option<Dir> = None;
                    match key.code {
                        KeyCode::Char('r') => {}
                        KeyCode::Char('w') => d = Some(Dir::Up),
                        KeyCode::Char('a') => d = Some(Dir::Left),
                        KeyCode::Char('s') => d = Some(Dir::Down),
                        KeyCode::Char('d') => d = Some(Dir::Right),
                        KeyCode::Char('i') => {
                            let blt = MoonBullet::new(self.mainship_pos.x, self.mainship_pos.y);
                            self.bullets.push(blt);
                        }
                        _ => {}
                    }
                    if d != None {
                        self.act(d.unwrap(), context);
                    }
                }
                _ => {}
            }
        }
        context.input_events.clear();
    }

    fn handle_auto(&mut self, _context: &mut Context, _dt: f32) {}
    fn handle_event(&mut self, _context: &mut Context, _dt: f32) {}
    fn handle_timer(&mut self, _context: &mut Context, _dt: f32) {}

    fn as_any(&mut self) -> &mut dyn Any {
        self
    }
}
